"""
schedule.py

Created by Steven Hepting on 2008-08-07.
Copyright (c) 2008 ProtoSpec Engineering. All rights reserved.

TODO: ensure to reset the lists at the end of each day (either call a list-parsing function every now and then, or have a timer, or something else)
"""

import sys
import re
import datetime
import time
import threading

import log
log = logging.getLogger()

class Time(object):
    """A time that the slight should switch"""
    def __init__(self, operation, hour, minute=0, second=0):
        self.time = datetime.time(hour, minute, second)
        self.operation = operation

    def previous(self):
        """Returns true if this time has already passed today"""
        now = datetime.datetime.now().strftime("%H %M %S") 
        then = self.time.strftime("%H %M %S")
        if now > then:
            return True

    def __str__(self):
        if self.time.second != 0:
            then = self.time.strftime("%I:%M:%S %p").lower()
        else:
            then = self.time.strftime("%I:%M %p").lower()
        return "%-3s at %s" % (self.operation, then)
        

class Schedule(object):
    """Keep scheduling data for an object"""
    def __init__(self, file="schedule.txt"):
        super(Schedule, self).__init__()
        self.file = file
        self.re_format = "(?P<op>on|off)( |\t)*(?P<hours>[0-9]{1,2})\
(:(?P<min>[0-9]{1,2}))?(:(?P<sec>[0-9]{1,2}))?(?P<ma>am|pm)"
        self.upcoming_times = []
        self.signalled_times = []
        
    def parse(self):
        """Read in a set of times from a file."""
        for line in open(self.file):
            if line[0] != '#':
                if line.strip() != "":                    
                    results = re.search(self.re_format, line)
                    operation = results.group('op')
                    if results.group('ma') == 'pm':
                        hours = int(results.group('hours')) + 12
                    else:
                        hours = int(results.group('hours'))
                    try:
                        minutes = int(results.group('min'))
                    except TypeError:
                        minutes = 0
                    try:
                        seconds = int(results.group('sec'))
                    except TypeError:
                        seconds = 0
                    
                    tm = Time(operation, hours, minutes, seconds)
                    if tm.previous():
                        self.signalled_times.append(tm)
                    else:
                        self.upcoming_times.append(tm)
    def run(self):
        """Run the scheduler in a thread to keep checking for events"""
        def check():
            """Check the next item to see if it's happened yet"""
            while (True):
                print datetime.datetime.now().strftime("%H:%M:%S")
                for tm in self.upcoming_times:
                    if tm.previous():
                        print "Timer event!"
                        self.signalled_times.append(self.upcoming_times.pop())
                time.sleep(3)
        th = threading.Thread(target=check)
        th.setDaemon(1)
        th.start()


    def __str__(self):
        signalled = "\n\t".join(["%s" % x for x in self.signalled_times])
        upcoming = "\n\t".join(["%s" % x for x in self.upcoming_times])
        return "Previously Today:\n\t%s\nUpcoming Today:\n\t%s" % \
                                                    (signalled, upcoming)


if __name__ == '__main__':
	sched = Schedule()
	sched.parse()
	print sched
	sched.run()
	time.sleep(5)
	sys.exit(0)
	print sched